package com.hoopchina.util.download;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import com.hoopchina.news.R;
import com.hoopchina.meta.NewsItem;
import com.hoopchina.meta.NewsItemDetail;
import com.hoopchina.meta.NewsItemDetail.Content;
import com.hoopchina.service.BaiduNews;
import com.hoopchina.util.LogUtils;
import com.hoopchina.util.PathUtils;
import com.hoopchina.util.UrlUtils;
import com.hoopchina.util.download.DownloadTask.Type;
import com.hoopchina.util.json.Json2Locallist;
import com.hoopchina.util.json.JsonEngine;
import com.hoopchina.util.xml.NewsDetailXML;
import com.hoopchina.util.xml.NewsItemXML;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.widget.RemoteViews;

public class DownloadMgr {

	private static DownloadMgr mInstance = null;
	private Context mContext = null;
	private static List<DownloadQueue> mQueueList = null;
	private QueueTask mOngoingQueueTask = null;
	private NotificationManager mNotiMgr = null;
	private Notification mNotification = null;

	public OnDownloadUpdateListener mOnDownloadUpdateListener = null;
	public static final String BROADCAST_ACTION = "com.hoopchina.util.download.DownloadMgr.BRODCAST_ACTION";
	public static final String CONST_STR_FLAG = "flag";
	public static final String CONST_STR_TOTAL = "total";
	public static final String CONST_STR_DONE = "doneNum";
	public static final int FLAG_VIEW_CHANGE = -8;

	private static final int NOTI_ID = 0;
	private static final int FLAG_UPDATE_TOTAL = 0;
	private static final int FLAG_UPDATE_PROGRESS = 1;
	private static final int FLAG_UPDATE_COMPLETE = 2;
	private static final String OFFLINE_DOWN_PATH = "/baidunews/offline/";
	private static final String DETAIL_URL_PREFIX = "http://newsmobile.baidu.com/n?m=app&v=detail&url=";

	public enum Status {
		ONGOING, PENDING, FINISHED
	}

	public void setDownloadUpdateListener(OnDownloadUpdateListener listener) {
		this.mOnDownloadUpdateListener = listener;
	}

	public interface OnDownloadUpdateListener {
		void onProgressUpdate(int done, int total, String type);

		void onDownloadFinished();
	}

	public static DownloadMgr getInstance() {

		if (mInstance == null) {
			synchronized (DownloadMgr.class) {
				if (mInstance == null) {
					mInstance = new DownloadMgr();
				}
			}
		}
		return mInstance;
	}

	private DownloadMgr() {
		mQueueList = new ArrayList<DownloadQueue>();
	}

	public void setContext(Context aContext) {
		mContext = aContext;
		this.mNotiMgr = (NotificationManager) aContext
				.getSystemService(Context.NOTIFICATION_SERVICE);
	}

	public void initNotification() {
		mNotification = new Notification(R.drawable.icon, "百度新闻离线下载",
				System.currentTimeMillis());
		mNotification.contentView = new RemoteViews(mContext.getPackageName(),
				R.layout.notificationview);
		mNotification.contentView.setProgressBar(R.id.offline_down_pb, 0, 0,
				false);
		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(BROADCAST_ACTION);
		PendingIntent contentIntent = PendingIntent.getBroadcast(mContext, 0,
				broadcastIntent, 0);
		mNotification.contentIntent = contentIntent;
		mNotiMgr.notify(NOTI_ID, mNotification);
	}

	public void completeNotification(String contentText) {
		LogUtils.d("in");
		PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0,
				null, 0);
		mNotification.flags = Notification.FLAG_AUTO_CANCEL;
		mNotification.defaults |= Notification.DEFAULT_SOUND;
		mNotification.setLatestEventInfo(mContext, "百度新闻", "\"" + contentText
				+ "\"下载完成", contentIntent);
		mNotiMgr.notify(NOTI_ID, mNotification);
		LogUtils.d("out");
	}

	public void updateNotification(int doneNum, int totalNum, String type) {
		LogUtils.d("in");
		int per = doneNum * 100 / (totalNum == 0 ? 10000 : totalNum);
		mNotification.contentView.setProgressBar(R.id.offline_down_pb, 100,
				per, false);
		mNotification.contentView.setTextViewText(R.id.offline_down_txtcontent,
				" " + type + "  (" + doneNum + "/" + totalNum + ")");
		mNotification.contentView.setTextViewText(R.id.offline_down_percent,
				per + "%");
		mNotiMgr.notify(NOTI_ID, mNotification);
		LogUtils.d("out");
	}

	public List<DownloadQueue> getQueue() {
		return mQueueList;
	}

	/**
	 * 添加离线下载任务（对外的接口）
	 * 
	 * @param aUrlString
	 *            不同分类所对应的链接
	 */
	public void enQueue(String url, String type, String cityCode) {
		LogUtils.d("in Catigory type = " + type);

		String downloadUrl = url;

		if (type.equalsIgnoreCase("本地")) {
			if (cityCode == null || cityCode.equalsIgnoreCase("")) {
				cityCode = "0";
			}
			url = url+ "&loc=" + cityCode;
			downloadUrl = downloadUrl + "&loc=" + cityCode + "&rn=40";
		} else {
			downloadUrl += "&rn=40";
		}

		if (isExisted(downloadUrl)) {
			// 如果添加的任务在队列中已经存在则直接return
			return;
		}

		DownloadQueue aNewQueue = new DownloadQueue(url, downloadUrl, type);
		mQueueList.add(aNewQueue);

		if (!hasOngoingQueue() && mQueueList.size() != 0) {
			start();
		}

		LogUtils.d("out");
	}

	private void start() {
		DownloadTask aXMLTask = null;
		if (mQueueList.get(0).getType().equalsIgnoreCase("本地")) {

			aXMLTask = new DownloadTask(mQueueList.get(0).getUrl(), mQueueList
					.get(0).getDownloadUrl(), OFFLINE_DOWN_PATH,
					DownloadTask.Type.JSON_LOCAL_LIST);

		} else {

			aXMLTask = new DownloadTask(mQueueList.get(0).getUrl(), mQueueList
					.get(0).getDownloadUrl(), OFFLINE_DOWN_PATH,
					DownloadTask.Type.XML_HOME_LIST);

		}

		mQueueList.get(0).setStatus(Status.ONGOING);

		mOngoingQueueTask = new QueueTask();
		mOngoingQueueTask.execute(aXMLTask);
	}

	public void cancel(int position) {

		if (position >= mQueueList.size() || position < 0) {
			return;
		}
		if (position == 0) {
			if (mOngoingQueueTask != null) {
				mOngoingQueueTask.cancel(true);
			}
			mNotiMgr.cancel(NOTI_ID);
		}

		mQueueList.remove(position);

		if (!hasOngoingQueue() && mQueueList.size() != 0) {
			start();
		}

	}

	public void cancelAll() {

		if (mOngoingQueueTask != null) {
			mOngoingQueueTask.cancel(true);
		}
		if (mQueueList != null) {
			mQueueList.clear();
		}

		mNotiMgr.cancel(NOTI_ID);
	}

	/**
	 * 检查请求李先下载的链接是否已经存在
	 * 
	 * @param aCatiUrl
	 * @return
	 */
	private boolean isExisted(String aCatiUrl) {
		for (DownloadQueue queueTask : mQueueList) {
			if (aCatiUrl.equalsIgnoreCase(queueTask.getDownloadUrl()))
				return true;
		}
		return false;
	}

	/**
	 * 检查是否有正在下载中的分类请求队列
	 * 
	 * @return
	 */
	private boolean hasOngoingQueue() {
		for (DownloadQueue queueTask : mQueueList) {
			if (queueTask.getStatus() == Status.ONGOING) {
				return true;
			}
		}
		return false;
	}

	class QueueTask extends AsyncTask<DownloadTask, Integer, String> {
		int mCounter = 0;

		@Override
		protected String doInBackground(DownloadTask... params) {
			LogUtils.d("thread ID = " + Thread.currentThread().getName());
			getTarget(params[0]);

			return null;
		}

		@Override
		protected void onPreExecute() {
			LogUtils.d("in");
			initNotification();
			if (mOnDownloadUpdateListener != null) {
				mOnDownloadUpdateListener.onProgressUpdate(0, 0, mQueueList
						.get(0).getType());
			}
			super.onPreExecute();
		}

		@Override
		protected void onPostExecute(String result) {
			LogUtils.d("in");
			if (mQueueList.get(0).getFinishedSize() == mQueueList.get(0)
					.getQueueSize()) {
				LogUtils.d(">>task finished<<");
				// completeNotification( mQueueList.get( 0 ).getType() );
				// if ( mOnDownloadUpdateListener != null ) {
				// mOnDownloadUpdateListener.onDownloadFinished();
				// }
			}
			// TODO: 任务失败如何显示？
			completeNotification(mQueueList.get(0).getType());
			if (mOnDownloadUpdateListener != null) {
				mOnDownloadUpdateListener.onDownloadFinished();
			}

			mQueueList.remove(0);
			if (!hasOngoingQueue() && mQueueList.size() != 0) {
				start();
			}
			super.onPostExecute(result);
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			LogUtils.d("in");
			if (values[0] == null)
				return;

			switch (values[0]) {
			case FLAG_UPDATE_TOTAL:
				updateNotification(0, mQueueList.get(0).getQueueSize(),
						mQueueList.get(0).getType());

				if (mOnDownloadUpdateListener != null) {
					mOnDownloadUpdateListener
							.onProgressUpdate(0, mQueueList.get(0)
									.getQueueSize(), mQueueList.get(0)
									.getType());
				}
				break;

			case FLAG_UPDATE_PROGRESS:
				// 更新Notification Bar
				LogUtils.d("done:" + mQueueList.get(0).getFinishedSize()
						+ " total = " + mQueueList.get(0).getQueueSize());

				updateNotification(mQueueList.get(0).getFinishedSize(),
						mQueueList.get(0).getQueueSize(), mQueueList.get(0)
								.getType());

				if (mOnDownloadUpdateListener != null) {
					// 更新DownloadActivity
					mOnDownloadUpdateListener.onProgressUpdate(mQueueList
							.get(0).getFinishedSize(), mQueueList.get(0)
							.getQueueSize(), mQueueList.get(0).getType());
				}

				break;

			default:
				break;

			}
			super.onProgressUpdate(values);
		}

		@Override
		protected void onCancelled() {
			LogUtils.d("in");
			super.onCancelled();
		}

		/**
		 * 下载分类队列中的文件
		 * 
		 * @param aTask
		 */
		protected void getTarget(DownloadTask aTask) {

			LogUtils.d("in, name = "
					+ UrlUtils.getNameFromUrl(aTask.getTargetUrl())
					+ " type = " + aTask.getType());

			if (isCancelled()) {
				LogUtils.d("isCancelled == true, return!");
				return;
			}

			DownloadExecutor.start(aTask, new DownloadCallback() {

				@Override
				public void onFinished(DownloadTask finishedTask) {

					LogUtils.d(" type = "
							+ finishedTask.getType());

					if (finishedTask.getType() == Type.XML_HOME_LIST
							|| finishedTask.hasImgFlag()
							|| finishedTask.getType() == Type.JSON_LOCAL_LIST) {
						parseFile(finishedTask);
					}

					switch (finishedTask.getType()) {

					case JSON_LOCAL_LIST:
					case XML_HOME_LIST:

						if (!isCancelled() && finishedTask.getStatus()) {
							publishProgress(FLAG_UPDATE_TOTAL, mQueueList
									.get(0).size());
						}

						while (mQueueList != null && mQueueList.get(0) != null
								&& !mQueueList.get(0).isEmpty()) {

							// 下载详情页XML
							getTarget(mQueueList.get(0).poll());

						}
						break;

					case XML_HOME_DETAIL:

						if (finishedTask.hasImgFlag()) {
							LogUtils.d("finished task has image");
							while (mQueueList != null
									&& mQueueList.get(0) != null
									&& !mQueueList.get(0).isEmpty()) {
								// 下载详情页中的图片
								getTarget(mQueueList.get(0).poll());
							}
						}
						mQueueList.get(0).setFinishedSize(++mCounter);
						// 先判断task的状态 再更新UI 进度
						if (!isCancelled() && finishedTask.getStatus()) {
							publishProgress(FLAG_UPDATE_PROGRESS);
						}
						LogUtils.d("queueList size = "
								+ mQueueList.get(0).size());

						if (mQueueList.get(0).isLastTask() && !isCancelled()
								&& finishedTask.getStatus()) {
							publishProgress(FLAG_UPDATE_COMPLETE);
						}
						break;

					default:
						break;
					}

				}

				@Override
				public void onFailed() {
					if (mOnDownloadUpdateListener != null) {

					}

				}
			});

			LogUtils.d("out, name = "
					+ UrlUtils.getNameFromUrl(aTask.getTargetUrl())
					+ " type = " + aTask.getType());
		}

		protected void parseFile(DownloadTask aXMLTask) {

			LogUtils.d("in");

			if (isCancelled()) {
				LogUtils.d("isCancelled == true, return!");
				return;
			}

			String aUrlString = "";
			if (aXMLTask.getType() == Type.XML_HOME_LIST
					|| aXMLTask.getType() == Type.JSON_LOCAL_LIST) {

				aUrlString = aXMLTask.getNameUrl();

			} else {

				aUrlString = aXMLTask.getTargetUrl();
			}
			 
			if (null == aUrlString || aUrlString.equalsIgnoreCase(""))
				return;
			
			LogUtils.d("xmlfile = "+UrlUtils.getNameFromUrl(aUrlString));

			final File xmlFile = UrlUtils.getFileFromUrl(OFFLINE_DOWN_PATH,
					aUrlString);

			if (!xmlFile.exists()) {
				// ERROR
				LogUtils.d("xmlFile not exists");
				return;
			}

			try {
				InputStream inputStream = new BufferedInputStream(
						new FileInputStream(xmlFile));

				switch (aXMLTask.getType()) {

				case JSON_LOCAL_LIST:
				case XML_HOME_LIST:
					List<NewsItem> newsList = null;
					if (aXMLTask.getType() == Type.JSON_LOCAL_LIST) {
						LogUtils.d("task type = JSON_LOCAL_LIST");
						String jsonString = JsonEngine
								.getJsonStrFromFile(inputStream);
						if (jsonString.equalsIgnoreCase("")) {
							return;
						}
						newsList = Json2Locallist.getLocalList(jsonString);
						// 把json String 保存成XML文件
						LogUtils.d("save to xml file name = "
								+ UrlUtils.getNameFromUrl(aXMLTask
										.getTargetUrl()));
						BaiduNews
								.localSave(newsList, OFFLINE_DOWN_PATH,
										UrlUtils.getNameFromUrl(aXMLTask
												.getTargetUrl()));
					} else {
						LogUtils.d("task type = XML_HOME_LIST");
						newsList = NewsItemXML.getNewsList(inputStream);
					}

					if (newsList == null) {
						return;
					}

					for (NewsItem aItem : newsList) {
						// 下载详情页XML

						if (isCancelled()) {
							LogUtils.d("isCancelled == true, return!");
							return;
						}

						DownloadTask aDetailXMLTask = new DownloadTask(
								DETAIL_URL_PREFIX + aItem.getUrl().trim(),
								OFFLINE_DOWN_PATH,
								DownloadTask.Type.XML_HOME_DETAIL);

						if (aItem.getImgUrl().equalsIgnoreCase("1")) {
							LogUtils.d("has img: " + aItem.getTitle());
							aDetailXMLTask.setImgFlag(true);
						}

						mQueueList.get(0).offer(aDetailXMLTask);
						LogUtils.d("for loop case 1: queue size = "
								+ mQueueList.get(0).size()
								+ "name = "
								+ UrlUtils.getNameFromUrl(aDetailXMLTask
										.getTargetUrl()));
					}
					mQueueList.get(0).setQueueSize(mQueueList.get(0).size());
					LogUtils.d("queue size = " + mQueueList.get(0).size());
					break;

				case XML_HOME_DETAIL:
					LogUtils.d("task type = XML_HOME_DETAIL");
					NewsDetailXML aDetailXML = new NewsDetailXML();
					NewsItemDetail aDetailInfo = aDetailXML
							.getNewsList(inputStream);

					if (aDetailInfo != null && aDetailInfo.getContent() != null
							&& aDetailInfo.getContent().size() != 0) {

						for (Content detail : aDetailInfo.getContent()) {

							if (isCancelled()) {
								LogUtils.d("isCancelled == true, return!");
								return;
							}

							if (detail.getType().equalsIgnoreCase("image")) {
								LogUtils.d("imgtask imgurl="
										+ detail.getSubContent()
										+ " file name = "
										+ UrlUtils.getNameFromUrl(detail
												.getSubContent().trim()));

								String imgUrl = detail.getSubContent();
								if (imgUrl.contains("&")) {
									// TODO: server端传的url有问题，暂时这样处理
									imgUrl = imgUrl.substring(
											imgUrl.lastIndexOf("http"),
											imgUrl.indexOf("&"));
									LogUtils.i("img url = " + imgUrl);
								}

								DownloadTask aImgTask = new DownloadTask(
										imgUrl, OFFLINE_DOWN_PATH,
										DownloadTask.Type.IMG);

								getTarget(aImgTask);
							}
						}

					}

					break;

				default:
					LogUtils.d("task type = default");
					break;
				}

			} catch (Exception e) {
				e.printStackTrace();
				LogUtils.e("Exception , e = " + e.toString());
			}
			LogUtils.d("out, filename = "
					+ UrlUtils.getNameFromUrl(aXMLTask.getTargetUrl()));

		}
	}

}